﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
//using System.Linq;
using System.Text;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
using DBSourceToolsLib;
using DBConnectionLib;
using DBSourceToolsLib.SysObjects;
using Fireball.Windows.Forms;
using Fireball.Syntax;
using Fireball.CodeEditor.SyntaxFiles;


namespace DBSourceTools
{
    public partial class SourceEditor : MainPanelForm
    {
        private ScriptRunner m_ScriptRunner;
        delegate void SetTextCallback(string text);
        private bool m_bIsQuery = false;
        private CodeEditorControl m_CodeEditor;
        private bool m_bIsRunning = false;

        public SourceEditor(string strDBName, string strObjType, string strName)
            : base(strDBName, strObjType, strName)
        {
            InitializeComponent();
        }

        private void SourceEditor_Load(object sender, EventArgs e)
        {
            this.Text = m_Name;
            this.TabText = m_Name;
            SysObjects sysObjects;
            SourceDatabase oDatabase = UserSettings.Instance().getSourceDatabase(m_DatabaseName);

            DBSourceToolsLib.SysObjects.SysObject mySysObject =
                oDatabase.SysObjects.getSysObject(m_ObjectType, m_Name);

            if (mySysObject != null)
                this.m_splitContainer.Panel1.Controls.Add((System.Windows.Forms.Panel)mySysObject.GetPanel()/* mySysObject.getPanel()*/);
            else
            {
                this.m_splitContainer.Panel1.Controls.Add(GetBlankPanel());
                this.m_bIsQuery = true;
            }

            this.m_splitContainer.Panel2Collapsed = true;

            this.m_CodeEditor = (CodeEditorControl)this.m_splitContainer.Panel1.Controls[0].Controls[0];

            this.Activated += new EventHandler(SourceEditor_Activated);
            m_ScriptRunner = new ScriptRunner(oDatabase, true);
            m_ScriptRunner.ProgressEventPublisher += new EventHandler<ProgressEventArgs>(oScriptRunner_ProgressEventPublisher);

        }

        private System.Windows.Forms.Panel GetBlankPanel()
        {
            Panel oPanel = new Panel();
            oPanel.Dock = DockStyle.Fill;

            CodeEditorControl codeEdit = new CodeEditorControl();
            codeEdit.Dock = DockStyle.Fill;

            CodeEditorSyntaxLoader.SetSyntax(codeEdit, SyntaxLanguage.SqlServer2K);
            codeEdit.Document.Text = this.Text;
            oPanel.Controls.Add(codeEdit);

            return oPanel;

        }

        void SourceEditor_Activated(object sender, EventArgs e)
        {
            this.m_Observer.NotifyEvent(this.m_DatabaseName, this.m_ObjectType, this.m_Name
                , DBSourceToolsLib.Interfaces.SourceEditorEvent.IsCurrent, null);

        }

        void SourceEditor_TextChanged(object sender, EventArgs e)
        {
            if (!this.TabText.Contains("*"))
                this.TabText += "*";
            if (!this.Text.Contains("*"))
                this.Text += "*";
            SourceDatabase oDatabase = UserSettings.Instance().getSourceDatabase(this.m_DatabaseName);
            if (!m_bIsQuery)
                oDatabase.SysObjects.getSysObject(this.m_ObjectType, this.m_Name).Text = m_CodeEditor.Document.Text;
        }

        private void OnFormClosed(object sender, FormClosedEventArgs e)
        {
        }


        private void runQueryToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.m_splitContainer.Panel2Collapsed = false;
            this.m_toolStripStatusLabelOutput.Text = "Executing ...";

            RunScript(this.m_DatabaseName, this.m_ObjectType, this.m_Name, m_CodeEditor.Selection.Text);
            this.m_bIsRunning = true;
        }


        private void hideOutputToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.m_splitContainer.Panel2Collapsed = (!this.m_splitContainer.Panel2Collapsed);
        }

        public void RunScript(string strDatabase, string strObjectType, string strName, string strSelectedText)
        {
            this.m_textBoxOutput.Clear();

            SysObjects sysObjects;
            SourceDatabase oDatabase = UserSettings.Instance().getSourceDatabase(strDatabase);

            string strExecuteText = "";
            if (strSelectedText.Length > 0)
            {
                strExecuteText = strSelectedText;
            }
            else
            {
                strExecuteText = m_CodeEditor.Document.Text;
            }

            m_ScriptRunner.RunScriptUsingStreams(this.m_Name, strExecuteText);
        }

        void oScriptRunner_ProgressEventPublisher(object sender, ProgressEventArgs e)
        {
            if (e.Percent.CompareTo("100") == 0)
            {
                this.SetText(this.m_ScriptRunner.GetResultsText());
                this.m_toolStripStatusLabelOutput.Text = "Done";
                this.m_bIsRunning = false;
            }
            this.SetText(e.Message + Environment.NewLine);
        }


        private void SetText(string text)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.m_textBoxOutput.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.m_textBoxOutput.AppendText(text);
                this.m_textBoxOutput.Update();
            }
        }

        private void abortScriptToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // ctrl-Z pressed
            if (this.m_bIsRunning)
            {
                this.m_toolStripStatusLabelOutput.Text = "Aborting ...";
                this.m_ScriptRunner.Abort();
                // do not call a join here -- dont understand why behaviour is different from GUI and nUnit
                //this.m_ScriptRunner.Join();
                this.m_toolStripStatusLabelOutput.Text = "Aborted";
            }
            else
            {
                this.m_CodeEditor.Document.Undo();
            }
        }

        private void runScriptStreamModeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.m_splitContainer.Panel2Collapsed = false;
            this.m_toolStripStatusLabelOutput.Text = "Executing ...";

            Fireball.Windows.Forms.CodeEditorControl oCodeEditor =
                (Fireball.Windows.Forms.CodeEditorControl)this.m_splitContainer.Panel1.Controls[0].Controls[0];

            RunScript(this.m_DatabaseName, this.m_ObjectType, this.m_Name, oCodeEditor.Selection.Text);
            this.m_bIsRunning = true;
        }


    }
}
